package
{
	public class MathContext
	{
		/* ----- Properties ----- */
		/* properties public constant */
		/**
		 * Plain (fixed point) notation, without any exponent. Used as a setting to
		 * control the form of the result of a <code>BigDecimal</code> operation. A
		 * zero result in plain form may have a decimal part of one or more zeros.
		 * 
		 * @see #ENGINEERING
		 * @see #SCIENTIFIC
		 * @stable ICU 2.0
		 */
		// --public static final int PLAIN=0; // [no exponent]
		public static const PLAIN:int = 0; // [no exponent]
		
		/**
		 * Standard floating point notation (with scientific exponential format, where
		 * there is one digit before any decimal point). Used as a setting to control
		 * the form of the result of a <code>BigDecimal</code> operation. A zero
		 * result in plain form may have a decimal part of one or more zeros.
		 * 
		 * @see #ENGINEERING
		 * @see #PLAIN
		 * @stable ICU 2.0
		 */
		// --public static final int SCIENTIFIC=1; // 1 digit before .
		public static const SCIENTIFIC:int= 1; // 1 digit before .
		
		/**
		 * Standard floating point notation (with engineering exponential format, where
		 * the power of ten is a multiple of 3). Used as a setting to control the form
		 * of the result of a <code>BigDecimal</code> operation. A zero result in
		 * plain form may have a decimal part of one or more zeros.
		 * 
		 * @see #PLAIN
		 * @see #SCIENTIFIC
		 * @stable ICU 2.0
		 */
		// --public static final int ENGINEERING=2; // 1-3 digits before .
		public static const ENGINEERING:int = 2; // 1-3 digits before .
		
		// The rounding modes match the original BigDecimal class values
		/**
		 * Rounding mode to round to a more positive number. Used as a setting to
		 * control the rounding mode used during a <code>BigDecimal</code> operation.
		 * <p>
		 * If any of the discarded digits are non-zero then the result should be rounded
		 * towards the next more positive digit.
		 * 
		 * @stable ICU 2.0
		 */
		// --public static final int ROUND_CEILING=2;
		public static const ROUND_CEILING:int = 2;

		/**
		 * Rounding mode to round towards zero. Used as a setting to control the
		 * rounding mode used during a <code>BigDecimal</code> operation.
		 * <p>
		 * All discarded digits are ignored (truncated). The result is neither
		 * incremented nor decremented.
		 * 
		 * @stable ICU 2.0
		 */
		// --public static final int ROUND_DOWN=1;
		public static const ROUND_DOWN:int = 1;

		/**
		 * Rounding mode to round to a more negative number. Used as a setting to
		 * control the rounding mode used during a <code>BigDecimal</code> operation.
		 * <p>
		 * If any of the discarded digits are non-zero then the result should be rounded
		 * towards the next more negative digit.
		 * 
		 * @stable ICU 2.0
		 */
		// --public static final int ROUND_FLOOR=3;
		public static const ROUND_FLOOR:int = 3;

		/**
		 * Rounding mode to round to nearest neighbor, where an equidistant value is
		 * rounded down. Used as a setting to control the rounding mode used during a
		 * <code>BigDecimal</code> operation.
		 * <p>
		 * If the discarded digits represent greater than half (0.5 times) the value of
		 * a one in the next position then the result should be rounded up (away from
		 * zero). Otherwise the discarded digits are ignored.
		 * 
		 * @stable ICU 2.0
		 */
		// --public static final int ROUND_HALF_DOWN=5;
		public static const ROUND_HALF_DOWN:int = 5;

		/**
		 * Rounding mode to round to nearest neighbor, where an equidistant value is
		 * rounded to the nearest even neighbor. Used as a setting to control the
		 * rounding mode used during a <code>BigDecimal</code> operation.
		 * <p>
		 * If the discarded digits represent greater than half (0.5 times) the value of
		 * a one in the next position then the result should be rounded up (away from
		 * zero). If they represent less than half, then the result should be rounded
		 * down.
		 * <p>
		 * Otherwise (they represent exactly half) the result is rounded down if its
		 * rightmost digit is even, or rounded up if its rightmost digit is odd (to make
		 * an even digit).
		 * 
		 * @stable ICU 2.0
		 */
		// --public static final int ROUND_HALF_EVEN=6;
		public static const ROUND_HALF_EVEN:int = 6;

		/**
		 * Rounding mode to round to nearest neighbor, where an equidistant value is
		 * rounded up. Used as a setting to control the rounding mode used during a
		 * <code>BigDecimal</code> operation.
		 * <p>
		 * If the discarded digits represent greater than or equal to half (0.5 times)
		 * the value of a one in the next position then the result should be rounded up
		 * (away from zero). Otherwise the discarded digits are ignored.
		 * 
		 * @stable ICU 2.0
		 */
		// --public static final int ROUND_HALF_UP=4;
		public static const ROUND_HALF_UP:int = 4;

		/**
		 * Rounding mode to assert that no rounding is necessary. Used as a setting to
		 * control the rounding mode used during a <code>BigDecimal</code> operation.
		 * <p>
		 * Rounding (potential loss of information) is not permitted. If any of the
		 * discarded digits are non-zero then an <code>ArithmeticException</code>
		 * should be thrown.
		 * 
		 * @stable ICU 2.0
		 */
		// --public static final int ROUND_UNNECESSARY=7;
		public static const ROUND_UNNECESSARY:int = 7;

		/**
		 * Rounding mode to round away from zero. Used as a setting to control the
		 * rounding mode used during a <code>BigDecimal</code> operation.
		 * <p>
		 * If any of the discarded digits are non-zero then the result will be rounded
		 * up (away from zero).
		 * 
		 * @stable ICU 2.0
		 */
		// --public static final int ROUND_UP=0;
		public static const ROUND_UP:int = 0;

		/* properties private constant */
		// default settings
		// --private static final int DEFAULT_FORM=SCIENTIFIC;
		// --private static final int DEFAULT_DIGITS=9;
		// --private static final boolean DEFAULT_LOSTDIGITS=false;
		// --private static final int DEFAULT_ROUNDINGMODE=ROUND_HALF_UP;
		public static const DEFAULT_FORM:int = SCIENTIFIC;
		public static const DEFAULT_DIGITS:int = 9;
		public static const DEFAULT_LOSTDIGITS:Boolean = false;
		public static const DEFAULT_ROUNDINGMODE:int = ROUND_HALF_UP;

		/* properties private constant */
		
		// --private static final int MIN_DIGITS=0; // smallest value for DIGITS.
		// --private static final int MAX_DIGITS=999999999; // largest value for DIGITS.
		// If increased,
		public static const MIN_DIGITS:int = 0; // smallest value for DIGITS.
		public static const MAX_DIGITS:int = 999999999; // largest value for DIGITS. If
												// increased,
		// the BigDecimal class may need update.
		// list of valid rounding mode values, most common two first
		// --private static final int ROUNDS[]=new
		// int[]{ROUND_HALF_UP,ROUND_UNNECESSARY,ROUND_CEILING,ROUND_DOWN,ROUND_FLOOR,ROUND_HALF_DOWN,ROUND_HALF_EVEN,ROUND_UP};
		[ArrayElementType('int')]
		public static const ROUNDS:Array = new Array(ROUND_HALF_UP,
				ROUND_UNNECESSARY,
				ROUND_CEILING, ROUND_DOWN,
				ROUND_FLOOR,
				ROUND_HALF_DOWN,
				ROUND_HALF_EVEN, ROUND_UP);

		// --private static final java.lang.String ROUNDWORDS[]=new
		// java.lang.String[]{"ROUND_HALF_UP","ROUND_UNNECESSARY","ROUND_CEILING","ROUND_DOWN","ROUND_FLOOR","ROUND_HALF_DOWN","ROUND_HALF_EVEN","ROUND_UP"};
		// // matching names of the ROUNDS values
		[ArrayElementType('String')]
		public static const ROUNDWORDS:Array= new Array("ROUND_HALF_UP",
				"ROUND_UNNECESSARY", "ROUND_CEILING", "ROUND_DOWN", "ROUND_FLOOR",
				"ROUND_HALF_DOWN", "ROUND_HALF_EVEN", "ROUND_UP"); // matching names of
																	// the ROUNDS values

		/* properties private constant unused */
		
		// Serialization version
		// --private static final long serialVersionUID=7163376998892515376L;
		/* properties public constant */
		/**
		 * A <code>MathContext</code> object initialized to the default settings for
		 * general-purpose arithmetic. That is,
		 * <code>digits=9 form=SCIENTIFIC lostDigits=false
		 * roundingMode=ROUND_HALF_UP</code>.
		 * 
		 * @see #SCIENTIFIC
		 * @see #ROUND_HALF_UP
		 * @stable ICU 2.0
		 */
		// --public static final com.ibm.icu.math.MathContext DEFAULT=new
		// com.ibm.icu.math.MathContext(DEFAULT_DIGITS,DEFAULT_FORM,DEFAULT_LOSTDIGITS,DEFAULT_ROUNDINGMODE);
		public static const DEFAULT:MathContext = new MathContext(
				DEFAULT_DIGITS,
				DEFAULT_FORM,
				DEFAULT_LOSTDIGITS,
				DEFAULT_ROUNDINGMODE);
		
		/* member properties */
		/**
		 * The number of digits (precision) to be used for an operation. A value of 0
		 * indicates that unlimited precision (as many digits as are required) will be
		 * used.
		 * <p>
		 * The {@link BigDecimal} operator methods use this value to determine the
		 * precision of results. Note that leading zeros (in the integer part of a
		 * number) are never significant.
		 * <p>
		 * <code>digits</code> will always be non-negative.
		 * 
		 * @serial
		 */
		// --int digits;
		private var _digits:int;
				
		/**
		 * The form of results from an operation.
		 * <p>
		 * The {@link BigDecimal} operator methods use this value to determine the form
		 * of results, in particular whether and how exponential notation should be
		 * used.
		 * 
		 * @see #ENGINEERING
		 * @see #PLAIN
		 * @see #SCIENTIFIC
		 * @serial
		 */
		// --int form; // values for this must fit in a byte
		private var _form:int;
		
		/**
		 * Controls whether lost digits checking is enabled for an operation. Set to
		 * <code>true</code> to enable checking, or to <code>false</code> to disable
		 * checking.
		 * <p>
		 * When enabled, the {@link BigDecimal} operator methods check the precision of
		 * their operand or operands, and throw an <code>ArithmeticException</code> if
		 * an operand is more precise than the digits setting (that is, digits would be
		 * lost). When disabled, operands are rounded to the specified digits.
		 * 
		 * @serial
		 */
		// --boolean lostDigits;
		private var _lostDigits:Boolean;
		
		/**
		 * The rounding algorithm to be used for an operation.
		 * <p>
		 * The {@link BigDecimal} operator methods use this value to determine the
		 * algorithm to be used when non-zero digits have to be discarded in order to
		 * reduce the precision of a result. The value must be one of the public
		 * constants whose name starts with <code>ROUND_</code>.
		 * 
		 * @see #ROUND_CEILING
		 * @see #ROUND_DOWN
		 * @see #ROUND_FLOOR
		 * @see #ROUND_HALF_DOWN
		 * @see #ROUND_HALF_EVEN
		 * @see #ROUND_HALF_UP
		 * @see #ROUND_UNNECESSARY
		 * @see #ROUND_UP
		 * @serial
		 */
		// --int roundingMode;
		private var _roundingMode:int;
		
		public function MathContext(digits:int = DEFAULT_DIGITS,
			form:int = DEFAULT_FORM,
			lostDigits:Boolean = DEFAULT_LOSTDIGITS,
			roundingMode:int = DEFAULT_ROUNDINGMODE){
			// set values, after checking
			if (digits != DEFAULT_DIGITS) {
				if (digits < MIN_DIGITS){
					throw new Error("MathContext(): Digits too small: " + digits);
				}
				if (digits > MAX_DIGITS){
					throw new Error("MathContext(): Digits too large: " + digits);
				}
			}
			switch(form){
				case SCIENTIFIC:
				case ENGINEERING:
				case PLAIN:
					break;
				default:
					throw new Error("MathContext() Bad form value: " + form);
			}
			
			if (!isValidRound(roundingMode)){
				throw new Error("MathContext(): Bad roundingMode value: " + roundingMode);
			}
						
			_digits = digits;
			_form = form;
			_lostDigits = lostDigits; // [no bad value possible]
			_roundingMode = roundingMode;								
		}
		
		//* member methods */
		
		/**
		 * Returns the digits setting. This value is always non-negative.
		 * 
		 * @return an <code>int</code> which is the value of the digits setting
		 * @stable ICU 2.0
		 */		
		// --public int getDigits(){		
		public function getDigits():int{
			return _digits;
		}
		public function get digits():int{
			return _digits;			
		}
		
		/**
		 * Returns the form setting. This will be one of {@link #ENGINEERING},
		 * {@link #PLAIN}, or {@link #SCIENTIFIC}.
		 * 
		 * @return an <code>int</code> which is the value of the form setting
		 * @stable ICU 2.0
		 */		
		// --public int getForm(){		
		public function getForm():int{
			return _form;
		}
		public function get form():int{
			return _form;			
		}
			
		/**
		 * Returns the lostDigits setting. This will be either <code>true</code>
		 * (enabled) or <code>false</code> (disabled).
		 * 
		 * @return a <code>boolean</code> which is the value of the lostDigits setting
		 * @stable ICU 2.0
		 */		
		// --public boolean getLostDigits(){		
		public function getLostDigits():Boolean{
			return _lostDigits;
		}
		public function get lostDigits():Boolean{
			return _lostDigits;
		}
		
		/**
		 * Returns the roundingMode setting. This will be one of {@link  #ROUND_CEILING},
		 * {@link  #ROUND_DOWN}, {@link  #ROUND_FLOOR}, {@link  #ROUND_HALF_DOWN},
		 * {@link  #ROUND_HALF_EVEN}, {@link  #ROUND_HALF_UP},
		 * {@link  #ROUND_UNNECESSARY}, or {@link  #ROUND_UP}.
		 * 
		 * @return an <code>int</code> which is the value of the roundingMode setting
		 * @stable ICU 2.0
		 */		
		// --public int getRoundingMode(){		
		public function getRoundingMode():int{
			return _roundingMode;
		}
		public function get roundingMode():int{
			return _roundingMode;
		}
		
		/**
		 * Returns the <code>MathContext</code> as a readable string. The
		 * <code>String</code> returned represents the settings of the
		 * <code>MathContext</code> object as four blank-delimited words separated by
		 * a single blank and with no leading or trailing blanks, as follows:
		 * <ol>
		 * <li> <code>digits=</code>, immediately followed by the value of the digits
		 * setting as a numeric word.
		 * <li> <code>form=</code>, immediately followed by the value of the form
		 * setting as an uppercase word (one of <code>SCIENTIFIC</code>,
		 * <code>PLAIN</code>, or <code>ENGINEERING</code>).
		 * <li> <code>lostDigits=</code>, immediately followed by the value of the
		 * lostDigits setting (<code>1</code> if enabled, <code>0</code> if
		 * disabled).
		 * <li> <code>roundingMode=</code>, immediately followed by the value of the
		 * roundingMode setting as a word. This word will be the same as the name of the
		 * corresponding public constant.
		 * </ol>
		 * <p>
		 * For example: <br>
		 * <code>
		 * digits=9 form=SCIENTIFIC lostDigits=0 roundingMode=ROUND_HALF_UP
		 * </code>
		 * <p>
		 * Additional words may be appended to the result of <code>toString</code> in
		 * the future if more properties are added to the class.
		 * 
		 * @return a <code>String</code> representing the context settings.
		 * @stable ICU 2.0
		 */		
		// --public java.lang.String toString(){		
		public function toString():String{
			var formstr:String = null;
			switch(_form){
				case SCIENTIFIC:
					formstr = "SCIENTIFIC";
					break;
				case ENGINEERING:
					formstr = "ENGINEERING";
					break;
				default :
					formstr = "PLAIN";
			}
			var roundword:String = null;
			for(var i:int = 0;i < ROUNDS.length;i++){
				if (_roundingMode == ROUNDS[i]) {
					roundword = ROUNDWORDS[i];
					break;
				}
			}
			return "digits=" + _digits + " " + "form=" + formstr + " "
					+ "lostDigits=" + (_lostDigits ? "1" : "0") + " "
					+ "roundingMode=" + roundword;			
		}
		
		/* <sgml> Test whether round is valid. </sgml> */
		// This could be made shared for use by BigDecimal for setScale.
		// --private static boolean isValidRound(int testround){		
		private function isValidRound(testround:int):Boolean{
			for(var i:int = 0;i < ROUNDS.length;i++){
				if(ROUNDS[i] == testround){
					return true;
				}
			}
			return false;
		}		
	}
}